// Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.

/*************************************************************************
   -------------------------------------------------------------------------
   $Id$
   $DateTime$
   Description: Shared parameters manager.
             System for managing storage and retrieval of shared parameters.

   -------------------------------------------------------------------------
   History:
   - 29:04:2010: Created by Paul Slinger

*************************************************************************/

////////////////////////////////////////////////////////////////////////////////////////////////////
// Using the Shared Parameters System
// ----------------------------------
//
// 1) Declare a shared parameters structure
//
//      BEGIN_SHARED_PARAMS(SMySharedParams)
//
//        inline SMySharedParams(const string &_someData) : someData(_someData)
//        {
//        }
//
//        string	someData;
//
//      END_SHARED_PARAMS
//
// 2) Define type information for the shared parameters structure
//
//      DEFINE_SHARED_PARAMS_TYPE_INFO(SMySharedParams)
//
// 2) Generate a 32 bit crc (optional)
//
//      uint32 crc32 = pSharedParamsManager->GenerateCRC32("Name goes here");
//
// 3) Register the shared parameters
//
//      pSharedParamsManager->Register(crc32, SMySharedParams("I like chocolate milk"));
//
//        or
//
//      pSharedParamsManager->Register("MySharedParams", SMySharedParams("I like chocolate milk"));
//
// 4) Retrieve the shared parameters
//
//      SMySharedParamsConstPtr	pSharedParams = CastSharedParamsPtr<SMySharedParams>pSharedParamsManager->Get(crc32);
//
//        or
//
//      SMySharedParamsConstPtr	pSharedParams = CastSharedParamsPtr<SMySharedParams>pSharedParamsManager->Get("Name goes here");
//
// Additional Info
// ---------------
// The shared parameters manager stores a map of names internally in order to catch crc collisions.
// This means that in the unlikely event of a name crc collision, GenerateCRC32() will return 0.
// Register() and Get() will both return a null pointer.
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <CrySystem/ISystem.h>
#include <CryMemory/STLPoolAllocator_ManyElems.h>
#include <CryCore/StlUtils.h>
#include "ISharedParamsManager.h"
#include "SharedParams/ISharedParams.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// Shared parameters manager class.
// System for managing storage and retrieval of game parameters.
////////////////////////////////////////////////////////////////////////////////////////////////////
class CSharedParamsManager : public ISharedParamsManager
{
public:

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Default constructor.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	CSharedParamsManager();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Destructor.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	~CSharedParamsManager();

	// ISharedParamsManager

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Generate unique 32 bit crc.
	//
	// Params: pName - unique name
	//
	// Return: unique 32 bit crc
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual uint32 GenerateCRC32(const char* pName);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Register shared parameters.
	//
	// Params: crc32        - unique 32 bit crc
	//				 sharedParams - shared parameters
	//
	// Return: pointer to shared parameters
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ISharedParamsConstPtr Register(uint32 crc32, const ISharedParams& sharedParams);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Register shared parameters.
	//
	// Params: pName        - unique name
	//				 sharedParams - shared parameters
	//
	// Return: pointer to shared parameters
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ISharedParamsConstPtr Register(const char* pName, const ISharedParams& sharedParams);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Remove shared parameters.
	//
	// Params: crc32 - unique 32 bit crc
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Remove(uint32 crc32);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Remove shared parameters.
	//
	// Params: pName - unique name
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Remove(const char* pName);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Remove all shared parameters by type.
	//
	// Params: typeInfo - type information of to be removed
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void RemoveByType(const CSharedParamsTypeInfo& typeInfo);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Get shared parameters.
	//
	// Params: crc32 - unique 32 bit crc
	//
	// Return: pointer to shared parameters
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ISharedParamsConstPtr Get(uint32 crc32) const;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Get shared parameters.
	//
	// Params: pName - unique name
	//
	// Return: pointer to shared parameters
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ISharedParamsConstPtr Get(const char* pName) const;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Reset.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Reset();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Release.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Release();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Get memory statistics.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void GetMemoryStatistics(ICrySizer* pSizer);

	// ~ISharedParamsManager

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Lock.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	void Lock();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Unlock.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	void Unlock();

private:

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Verify unlocked.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	bool VerifyUnlocked() const;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Map of names.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	typedef std::unordered_map<uint32, string, std::hash<uint32>, std::equal_to<uint32>, stl::STLPoolAllocator_ManyElems<std::pair<const uint32, string>>> TNameMap;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Map of shared parameters.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	typedef std::unordered_map<uint32, ISharedParamsPtr, std::hash<uint32>, std::equal_to<uint32>, stl::STLPoolAllocator_ManyElems<std::pair<const uint32, ISharedParamsPtr>>> TRecordMap;

	TNameMap     m_names;

	TRecordMap   m_records;

	size_t       m_sizeOfSharedParams;

	bool         m_lock;

	mutable bool m_outputLockWarning;
};
